package com.aternity.geolocations.transregions;

import com.aternity.common.geolocation.CoordinatesLookupServiceImpl;
import com.aternity.common.geolocation.GeoCoordinates;
import com.aternity.common.geolocation.GeoLocation;
import com.aternity.common.geolocation.ReverseGeoCodingDataAccess;
import com.aternity.system.common.csv.CSVRWFactoryImpl;
import com.aternity.system.common.utils.CollectionUtils;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import com.maxmind.geoip.Location;
import com.maxmind.geoip.LookupService;
import org.apache.commons.codec.language.Metaphone;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.*;

/**
 * @author Daniel Orr
 */
public class MaxMindTraversal {

    private static final Logger logger = LoggerFactory.getLogger(MaxMindTraversal.class);

    Table<String, String, String> table = HashBasedTable.create();
    LookupService maxmindLookupService;
    ReverseGeoCodingDataAccess reverseGeoCodingDataAccess;
    CoordinatesLookupServiceImpl coordinatesLookupService;

    Metaphone metaphone = new Metaphone();
    Map<String, Set<GeoCoordinates>> diffs = new HashMap<>();

    public MaxMindTraversal() {
        loadMaxMindData();
        reverseGeoCodingDataAccess = new ReverseGeoCodingDataAccess(CSVRWFactoryImpl.getInstance());
        reverseGeoCodingDataAccess.init();
        coordinatesLookupService = new CoordinatesLookupServiceImpl();
        coordinatesLookupService.setReverseGeoCodingDataAccess(reverseGeoCodingDataAccess);
    }

    private void loadMaxMindData() {
        final String aternityHome = "c:\\dev\\server-7-2\\output\\aternity";
        System.setProperty("aternity.home", aternityHome);
        Path dataFile = FileSystems.getDefault().getPath(aternityHome, "geo_locations", "GeoIp.dat");
        try {
            logger.info("Loading maxmind data");
            maxmindLookupService = new LookupService(dataFile.toAbsolutePath().toString(), LookupService.GEOIP_MEMORY_CACHE);
            logger.info("Completed loading maxmind data");
        } catch (IOException e) {
            logger.error("Problem loading maxmind data", e);
        }
    }

    void traverse1() {
        long l = 0;
        for (int i = 0; i < 256; i++) {
            for (int j = 0; j < 256; j++) {
                for (int k = 0; k < 256; k++) {
                    String ip = i + "." + j + "." + k + ".0";
                    
                    Location location = maxmindLookupService.getLocation(ip);
                    if (location == null) {
                        if (!ip.startsWith("0.")){
                            System.out.println("");
                        }
                        continue;
                    }
                    GeoLocation geoLocation = coordinatesLookupService.lookupByCoordinates(location.longitude, location.latitude);
                    if (geoLocation == null) {
                        continue;
                    }
                    l++;
                    if (!location.countryName.equals(geoLocation.getCountry())) {
                        if (metaphone.isMetaphoneEqual(location.countryName, geoLocation.getCountry())) {
                            continue;
                        }
                        String key = location.countryName + "!=" + geoLocation.getCountry();
                        Set<GeoCoordinates> geoCoordinates = diffs.get(key);
                        if (geoCoordinates == null) {
                            geoCoordinates = new HashSet<>();
                            diffs.put(key, geoCoordinates);
                        }
                        geoCoordinates.add(new GeoCoordinates(location.longitude, location.latitude));
                    }
                }
            }
        }

        for (Map.Entry<String, Set<GeoCoordinates>> diff : diffs.entrySet()) {
            System.out.println("-----------------------------");
            System.out.println(diff.getKey());
            Set<GeoCoordinates> values = diff.getValue();
            for (GeoCoordinates geoCoordinates : values) {
                System.out.println(geoCoordinates);
            }
            System.out.println();
        }
        System.out.println("Processed " + l + " IPs");
    }

    public static void main(String[] args) {
        MaxMindTraversal mmt = new MaxMindTraversal();
        mmt.traverse1();
    }
}
